package com.xuecheng.media.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CoursePubDTO;
import com.xuecheng.api.content.model.dto.TeachplanDTO;
import com.xuecheng.api.media.model.ResourceUrlModel;
import com.xuecheng.api.media.model.dto.LiveCourseDTO;
import com.xuecheng.api.media.model.qo.QueryLiveCourseModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.content.CourseGradeEnum;
import com.xuecheng.common.enums.content.CourseModeEnum;
import com.xuecheng.common.enums.content.TeachPlanEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.media.agent.ContentApiAgent;
import com.xuecheng.media.common.constant.MediaErrorCode;
import com.xuecheng.media.common.utils.AliyunLiveUtil;
import com.xuecheng.media.config.AliyunLiveConfig;
import com.xuecheng.media.convert.LiveCourseConvert;
import com.xuecheng.media.entity.LiveCourse;
import com.xuecheng.media.mapper.LiveCourseMapper;
import com.xuecheng.media.service.LiveCourseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 直播课程 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class LiveCourseServiceImpl extends ServiceImpl<LiveCourseMapper, LiveCourse> implements LiveCourseService {

    @Autowired
    private ContentApiAgent contentApiAgent;

    @Autowired
    private AliyunLiveConfig aliyunLiveConfig;

    /**
     * 直播列表查询
     *
     * @param params    分页参数
     * @param model     条件查询模型
     * @param companyId 机构id
     */
    @Override
    public PageVO<LiveCourseDTO> queryLiveCourseList(PageRequestParams params, QueryLiveCourseModel model, Long companyId) {

        //判断关键的业务数据(分页数据、条件查询)
        Long pageNo = params.getPageNo();
        Integer pageSize = params.getPageSize();
        if (pageNo < 1) {
            pageNo = PageRequestParams.DEFAULT_PAGE_NUM;
        }

        if (pageSize < 1) {
            pageSize = PageRequestParams.DEFAULT_PAGE_SIZE;
        }

        //构建查询条件对象
        LambdaQueryWrapper<LiveCourse> queryWrapper = new LambdaQueryWrapper<>();

        //查询直播名称 like模糊查询并判断条件是否为空
        queryWrapper.like(StringUtil.isNotBlank(model.getCourseName()), LiveCourse::getCourseName, model.getCourseName());


        //查询机构Id
        queryWrapper.eq(LiveCourse::getCompanyId, companyId);

        //创建出分页数据
        Page<LiveCourse> page = new Page<>(pageNo, pageSize);

        //查询数据
        Page<LiveCourse> pageResult = this.page(page, queryWrapper);

        //封装查询数据
        List<LiveCourse> records = pageResult.getRecords();

        long total = pageResult.getTotal();

        //将pos转为dtos
        List<LiveCourseDTO> dtos = Collections.emptyList();
        if (!ObjectUtils.isEmpty(records)) {
            dtos = LiveCourseConvert.INSTANCE.entitys2dtos(records);
        }

        PageVO pageVO = new PageVO(dtos, total, pageNo, pageSize);

        return pageVO;
    }


    /**
     * <p>
     * 获取直播推流地址
     * </p>
     *
     * @param coursePubId 课程发布id
     * @param teachplanId 课程计划id
     * @return ResourceUrlModel
     */
    @Override
    public ResourceUrlModel getLivePushUrl(Long coursePubId, Long teachplanId) {
        ResourceUrlModel resourceUrlModel = new ResourceUrlModel(0);
        ExceptionCast.cast((coursePubId == null && coursePubId < 0) || teachplanId == null, CommonErrorCode.E_100101);
        //获取直播的课程发布信息
        RestResponse<CoursePubDTO> restResponse = contentApiAgent.getCoursePubById(coursePubId);
        if (!(restResponse.isSuccessful())) {
            ExceptionCast.cast(MediaErrorCode.E_140011);
        }
        CoursePubDTO coursePubDTO = restResponse.getResult();
        ExceptionCast.cast(coursePubDTO == null, MediaErrorCode.E_140103);
        TeachplanDTO teachplanDto = JSON.parseObject(coursePubDTO.getTeachplan(), TeachplanDTO.class);
        TeachplanDTO thTeach = this.getTeachplanDTOById(teachplanDto, teachplanId);
        if (thTeach == null) {
            resourceUrlModel.wrong(CommonErrorCode.E_100107);
            return resourceUrlModel;
        }
        String pushUrl = AliyunLiveUtil.getLivePushUrl(coursePubId, teachplanId, aliyunLiveConfig);

        LambdaUpdateWrapper<LiveCourse> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(LiveCourse::getTeachplanId, teachplanId);
        wrapper.set(LiveCourse::getPushUrl, pushUrl);
        this.update(wrapper);

        ResourceUrlModel livePullUrl = getLivePullUrl(coursePubId, teachplanId);

        resourceUrlModel.setPushUrl(pushUrl);
        resourceUrlModel.setPlayUrl(livePullUrl.getPlayUrl());
        return resourceUrlModel;
    }

    private TeachplanDTO getTeachplanDTOById(TeachplanDTO parentTeachplanDto, Long teachplanId) {
        if (parentTeachplanDto.getTeachPlanId().equals(teachplanId)) {
            return parentTeachplanDto;
        }
        if (!CollectionUtils.isEmpty(parentTeachplanDto.getTeachPlanTreeNodes())) {
            for (TeachplanDTO currentTeachplan : parentTeachplanDto.getTeachPlanTreeNodes()) {
                TeachplanDTO teachplanDTO = getTeachplanDTOById(currentTeachplan, teachplanId);
                if (teachplanDTO != null) {
                    return teachplanDTO;
                }
            }
        }
        return null;
    }

    /**
     * <p>
     * 获取直播播流地址
     * </p>
     *
     * @param coursePubId 课程发布id
     * @param teachplanId 课程计划id
     * @return ResourceUrlModel
     */
    @Override
    public ResourceUrlModel getLivePullUrl(Long coursePubId, Long teachplanId) {
        RestResponse<CoursePubDTO> restResponse = this.contentApiAgent.getCoursePubById(coursePubId);
        if (!(restResponse.isSuccessful())) {
            ExceptionCast.cast(MediaErrorCode.E_140102);
        }
        CoursePubDTO coursePubDTO = restResponse.getResult();
        String teachplanString = coursePubDTO.getTeachplan();
        TeachplanDTO teachplanDTO = JSON.parseObject(teachplanString, TeachplanDTO.class);

        if (ObjectUtils.isEmpty(teachplanDTO)) {
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }
        //获得三级课程计划
        TeachplanDTO tDTO = this.getTeachplanDTOById(teachplanDTO, teachplanId);
        ResourceUrlModel resourceUrlModel = new ResourceUrlModel();
        if (ObjectUtils.isEmpty(tDTO)) {
            resourceUrlModel.wrong(CommonErrorCode.E_100104);
        }
        String livePullUrl = AliyunLiveUtil.getLivePullUrl(coursePubId, teachplanId, aliyunLiveConfig);
        resourceUrlModel.setPlayUrl(livePullUrl);

        LambdaUpdateWrapper<LiveCourse> queryWrapper = new LambdaUpdateWrapper<>();
        queryWrapper.eq(LiveCourse::getTeachplanId, teachplanId);
        queryWrapper.set(LiveCourse::getPlayUrl, livePullUrl);
        this.update(queryWrapper);

        return resourceUrlModel;
    }

    /**
     * <p>
     * 根据课程id生成此课程下所有直播章节的直播课程记录
     * </p>
     *
     * @param courseId 课程id
     */
    @Override
    @Transactional
    public void createLiveCourseList(Long courseId) {

        RestResponse<CoursePubDTO> resp = contentApiAgent.getCoursePubByCourseId(courseId);
        if (!resp.isSuccessful()) {
            ExceptionCast.cast(CommonErrorCode.E_100106);
        }
        CoursePubDTO coursePubDTO = resp.getResult();
        //空或不是直播课程则不生成
        if (ObjectUtils.isEmpty(coursePubDTO) ||
                !coursePubDTO.getTeachmode().equals(CourseModeEnum.COURSE_MODE_LIVE_STATUS.getCode())) {
            ExceptionCast.cast(MediaErrorCode.E_140103);
        }

        String teachplan = coursePubDTO.getTeachplan();
        TeachplanDTO teachplanDTO = JSON.parseObject(teachplan, TeachplanDTO.class);
        //要生成的直播课程记录列表
        List<LiveCourse> liveCourseList = new LinkedList<>();
        this.generateLiveCourseList(liveCourseList, teachplanDTO, coursePubDTO);

        for (LiveCourse liveCourse : liveCourseList) {

            LambdaQueryWrapper<LiveCourse> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(LiveCourse::getCoursePubId, liveCourse.getCoursePubId());
            queryWrapper.eq(LiveCourse::getTeachplanId, liveCourse.getTeachplanId());

            // 根据课程发布Id和课程计划判断数据是否存在
            LiveCourse one = this.getOne(queryWrapper);

            // 如果直播记录已存在则赋值Id值做修改操作
            if (!(ObjectUtils.isEmpty(one))) {
                liveCourse.setId(one.getId());
            }
        }
        boolean result = this.saveOrUpdateBatch(liveCourseList);

        if (!result) {
            ExceptionCast.cast(MediaErrorCode.E_140104);
        }
    }

    /**
     * <p>
     * 递归查找直播课程计划
     * </p>
     *
     * @param liveCourseList 要生成的记录列表
     * @param teachplanDTO   课程计划
     * @param coursePubDTO   课程发布信息
     */
    private void generateLiveCourseList(List<LiveCourse> liveCourseList,
                                        TeachplanDTO teachplanDTO,
                                        CoursePubDTO coursePubDTO) {
        List<TeachplanDTO> treeNodes = teachplanDTO.getTeachPlanTreeNodes();
        if (!CollectionUtils.isEmpty(treeNodes)) {
            //课程计划子列表不为空才进入
            for (TeachplanDTO treeNode : treeNodes) {
                if (Objects.equals(TeachPlanEnum.THIRD_LEVEL, treeNode.getGrade())) {
                    LiveCourse liveCourse = fillDataToLiveCourse(treeNode, coursePubDTO);
                    liveCourseList.add(liveCourse);
                } else {
                    generateLiveCourseList(liveCourseList, treeNode, coursePubDTO);
                }
            }
        }
    }

    private LiveCourse fillDataToLiveCourse(TeachplanDTO treeNode, CoursePubDTO coursePubDTO) {

        LiveCourse liveCourse = new LiveCourse();
        liveCourse.setCourseId(coursePubDTO.getCourseId());
        liveCourse.setCourseName(coursePubDTO.getName());
        liveCourse.setTeachplanId(treeNode.getTeachPlanId());
        liveCourse.setCompanyId(coursePubDTO.getCompanyId());
        liveCourse.setCompanyName(coursePubDTO.getCompanyName());
        liveCourse.setTeachplanName(treeNode.getPname());
        liveCourse.setLiveStart(treeNode.getStartTime());
        liveCourse.setLiveEnd(treeNode.getEndTime());
        liveCourse.setIsPreview(treeNode.getIsPreview());
        //讲课人通过消息生成
        //liveCourse.setUsername(null);

        return liveCourse;
    }
}
